/*
 * This file is part of the Sx Framework Library.
 * 
 * Copyright (C) 2013 University of Colorado Denver
 * <min.choi@ucdenver.edu> <shane.transue@ucdenver.edu>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 */
#include <sxOpenGL_DefaultMassSpringMeshRenderer.h>
#include <sxOpenGL.h>

Sx::Simulation::Objects::Rendering::OpenGL_DefaultMassSpringMeshRenderer::OpenGL_DefaultMassSpringMeshRenderer(const std::shared_ptr<GraphicsContext>& graphicsContext) : SimulationObjectRenderer(graphicsContext) {}

Sx::Simulation::Objects::Rendering::OpenGL_DefaultMassSpringMeshRenderer::OpenGL_DefaultMassSpringMeshRenderer(const std::shared_ptr<GraphicsContext>& graphicsContext, float r, float g, float b) : SimulationObjectRenderer(graphicsContext) {
	this->r = r;
	this->g = g;
	this->b = b;
}

Sx::Simulation::Objects::Rendering::OpenGL_DefaultMassSpringMeshRenderer::~OpenGL_DefaultMassSpringMeshRenderer() {}

bool Sx::Simulation::Objects::Rendering::OpenGL_DefaultMassSpringMeshRenderer::construct(OpenGL_Context* graphicsContext, Mesh* mesh, MassSpringSystem* const massSpringSystem) {
	return false;
}

void Sx::Simulation::Objects::Rendering::OpenGL_DefaultMassSpringMeshRenderer::update(OpenGL_Context* graphicsContext, Mesh* mesh, double dt) {
	return;
}

bool SamePoint(const Eigen::Vector3d& originalPosition, const Eigen::Vector3d& newPosition, double threshold = 0.0001) {
	double xDiff = std::abs(newPosition.x() - originalPosition.x());
	double yDiff = std::abs(newPosition.y() - originalPosition.y());
	double zDiff = std::abs(newPosition.z() - originalPosition.z());
	if ( xDiff > threshold ) return false;
	if ( yDiff > threshold ) return false;
	if ( zDiff > threshold ) return false;
	return true;
}

void Sx::Simulation::Objects::Rendering::OpenGL_DefaultMassSpringMeshRenderer::render(OpenGL_Context* graphicsContext, Mesh* mesh, MassSpringSystem* const massSpringSystem) {
	//--------------------------------------------------------------------------
	// The renderer implementation needs to be mindful of the internal
	// representation type of the simulation. The graphics representation
	// generally does not need a high level of precision for most applications.
	//--------------------------------------------------------------------------

	glPushMatrix();
	glMultMatrixf(mesh->transformation().toMatrix4f().data());
	glPointSize(4.0f);
	glBegin(GL_POINTS);
		for ( unsigned int i = 0; i < massSpringSystem->getVertices().size(); i++ ) {
			glColor3f(0.5f, 0.7f, 0.9f);
			glVertex3dv(massSpringSystem->getNodePosition(i).data());
		}
	glEnd();

	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glColor3fv(mesh->getColorSolid());
	glBegin(GL_TRIANGLES);
		for ( unsigned int i = 0; i < mesh->getFaces().size(); i++ ) {
			for ( unsigned int x = 0; x < mesh->getFaces()[i].indices.size(); x++ ) {
				glVertex3dv(massSpringSystem->getVertices()[mesh->getFaces()[i].indices[x]].data());
				//glVertex3dv(massSpringSystem->getNodePosition(mesh->getFaces()[i].indices[x]).data());
			}
		}
	glEnd();

	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	glPolygonOffset(1.0, 2);
	glColor3f(mesh->getColorSolid().getR() - 0.2f, mesh->getColorSolid().getG() - 0.2f, mesh->getColorSolid().getB() - 0.2f);
	glBegin(GL_TRIANGLES);
		for ( unsigned int i = 0; i < mesh->getFaces().size(); i++ ) {
			for ( unsigned int x = 0; x < mesh->getFaces()[i].indices.size(); x++ ) {
				glVertex3dv(massSpringSystem->getVertices()[mesh->getFaces()[i].indices[x]].data());
				//glVertex3dv(massSpringSystem->getNodePosition(mesh->getFaces()[i].indices[x]).data());
			}
		}
	glEnd();
	glPopMatrix();
	
}
